﻿using System.Collections.Generic;
using System.Linq;
using MenesDroid.EngineCharacter;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using XNA_Game_Engine.Characters;
using XNA_Game_Engine.Events;
using XNA_Game_Engine.Map;
using XNA_Game_Engine.GUI;
using System;
using XNA_Game_Engine.Canvas;
using XNA_Game_Engine.Sounds;

namespace XNA_Game_Engine
{
    class EventHandler
    {
        private readonly LinkedList<Character> _objects = new LinkedList<Character>();
        private LinkedList<Event> events = new LinkedList<Event>();
        private Robot player;
        private Enemy enemy;
        private int [,] layer2;
        private int[,] layer1;
        private int width, height;
        private IsometricTilemap map;
        GameCanvas game;
        private List<Enemy> enemiesList = new List<Enemy>();
        private AnimatedSprite EnemySprite;
        private int XCheckPoint;
        private int YCheckPoint;
        private Arrow arrow;
        public static List<Score> levelScores = new List<Score>();
        private float timer = 0.0f;
        private bool canCheckKilling = true; // gambiarra mode on


        public EventHandler(Robot plyr, Enemy enmy, IsometricTilemap map, GameCanvas game)
        {
            this.player = plyr;
            this.enemy = enmy;
            this.map = map;
            this.width = map.Width;
            this.height = map.Height;
            this.game = game;
            this.layer2 = map.getLayer2();
            this.layer1 = map.getLayer1();
            //addEvent();
        }

       

        public void setSprites(AnimatedSprite sprite, Texture2D arrowSprite, Texture2D arrowExplos)
        {
            arrow = new Arrow(arrowSprite, arrowExplos);

            this.EnemySprite = sprite;

            addEvent();
        }


        public void addEvent()
        {
            
            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width; i++)
                {
                    switch (layer2[j, i])
                    {
                        case Flags.checkpoint:
                            {
                                events.AddLast(new Event(Flags.checkpoint, i, j));
                                XCheckPoint = i;
                                YCheckPoint = j;
                                break;
                            }                            

                        case Flags.trap:
                            {
                                events.AddLast(new Event(Flags.trap, i, j));
                                break;
                            }                            

                        case Flags.enemySpawn:
                            {                               
                                createEnemies(i, j);

                                break;
                            }                            

                        case Flags.playerSpawn:
                            {                               
                                createPlayer(i ,j);

                                //createEnemies(i, j); // testing
                                break;
                            }
                    }                  

                }
            }
            
            setDirection();
        }

        private void createEnemies(int x, int y )
        {
            
            //enemiesList.Add(new Enemy(2, 7, EnemySprite, map));
            //enemiesList.Add(new Enemy(8, 6, EnemySprite, map));
            //enemiesList.Add(new Enemy(4, 1, EnemySprite, map));

            enemiesList.Add(new Enemy(x, y, EnemySprite, map));

           // enemy.X = x;
           // enemy.Y = y;
            
           // enemy.enemyXInicial = x;
            //enemy.enemyYInicial = y;

        }

        private void createPlayer( int x, int y)
        {
            player.X = x;
            player.Y = y;
            player.XInicial = x;
            player.YInicial = y;   
        }

        private void setDirection()
        {
            player.setPlrSpawnDirectionFrame(new Vector2((int) XCheckPoint, (int) YCheckPoint));

            for (int i = 0; i < enemiesList.Count; i++)
            {
                Enemy enmy = enemiesList[i];    
                enmy.setEnemySpawnDirectionFrame(new Vector2((int)player.X, (int)player.Y));                
            }
        }


        public void Update(float difftime){

            for (int i = 0; i < enemiesList.Count; i++)
            {
                Enemy enmy = enemiesList[i];
                enmy.Update(difftime);
                verifyEnemyKilling(enmy, difftime);
                enmy.verifyEnemyProximity(difftime, new Vector2((int)player.X, (int)player.Y), new Vector2(player.xDir, player.yDir));
            }

            arrow.Update(difftime);

            if (StaticGui.gameStarted)
            {      
                    verifyEventsColision();
                    verifyWallColiding();
            }
            else
                restartOriginalsPositions();

        }

        public void Render(SpriteBatch renderTarget)
        {
            for (int i = 0; i < enemiesList.Count; i++)
            {
                Enemy enmy = enemiesList[i];
                enmy.Render(renderTarget);
            }

            arrow.Render(renderTarget);
        }

        private void verifyWallColiding()
        {
            if (StaticGui.gameStarted)
            {
                int x = (int)player.X /*+ player.xDir*/;
                int y = (int)player.Y /*+ player.yDir*/;
                                
                if (x<=8 && layer2[y, x + 1] == 10) // Pode Pular se na frente for uma plataforma
                    player.canJump = true;
                else                
                    player.canJump = false;
                

                if (layer2[y, x] > 0 && layer2[y, x] < 1000)
                {                    
                    if (layer2[y, x] != 10 || !player.isJumping()) // Plataforma alta
                    {                        
                        player.X = player.oldX;
                        player.Y = player.oldY;
                        player.isAbovePlataform = true;
                    }                   
                }

                if (layer1[y, x] == 0) // Se for buraco. Colide
                {
                    player.X = player.oldX;
                    player.Y = player.oldY;                   
                }

                player.isAbovePlataform = false;
            }
        }

        private void verifyEnemyKilling(Enemy enmy, float difftime)
        {
            timer += difftime;
            
            if (player.X == enmy.X && player.Y == enmy.Y && canCheckKilling)
            {
                canCheckKilling = false;                
                player.PlrDead = true;                 // Ativa a renderizacao do efeito.
                SoundController.playClip("enemyKill");
            }
            if (timer >= 2000)
            {
                timer = 0;
                canCheckKilling = true;
            }
        }
               
        private void restartOriginalsPositions()
        {
            foreach (Enemy enmy in enemiesList)
            {
                enmy.restartOriginalPositions();
            }

            player.restartOriginalPositions();    
        }

        private void verifyEventsColision()
        {
            for (int i = 0; i < events.Count; i++)
            {
                Event even = (Event) events.ElementAt(i);
               
                if (player.X == even.X && player.Y == even.Y)
                {
                    switch (even.Flag)
                    {
                        case 1000:
                            {
                                game.LevelCompleted();
                                addScore();
                                StaticGui.TimeStart.FinishGame();
                            }
                            break;                                                

                        case 4000: // TRAP
                            {
                                arrow.startArrow((int)player.X);
                                if (arrow.checkColision((int) player.X, (int)player.Y))
                                {                                     
                                     StaticGui.TimeStart.Stop();
                                     SoundController.playClip("death");
                                }
                            }
                            break;
                    }
                }
            }
        }

        private void addScore()
        {
            bool naoAchou = true;

            float newScore = (1000 / (float)(StaticGui.runningTime/1000)) * 10;
            

            //Console.WriteLine(StaticGui.runningTime/1000);
            int index = ActionsHandler.level;

            if (levelScores.Count == 0)
            {
                //Console.WriteLine("\n\nAdding First index");
                levelScores.Add(new Score(index, newScore));
                game.renderScore(0, newScore, true);
            }
            else
            {
                for (int i = 0; i < levelScores.Count; i++)
                {
                    Score score = levelScores[i];

                    if (score.getFase() == index)
                    {
                        float oldScore = score.getScore();
                        //Console.WriteLine("\n\nOld Score: " + oldScore);
                       // Console.WriteLine("New Score: " + newScore);

                        if (newScore < oldScore)
                        {
                            //Console.WriteLine("Replacing index " + (score.getFase()));                           
                            game.renderScore(oldScore, newScore, false);
                            naoAchou = false;
                            break;
                        }
                        else
                        {
                            score.setNewScore(newScore);
                            game.renderScore(oldScore, newScore, true);
                            naoAchou = false;
                            break;
                        }
                    }                   
                }
               

                if (naoAchou)
                {
                    //Console.WriteLine("\n\nAdding new index");
                    levelScores.Add(new Score(index, newScore));
                    game.renderScore(0, newScore, true);
                }

            }
        }

        //private void addScore()
        //{
        //    float newScore = (float)StaticGui.runningTime * 10;

        //    int index = ActionsHandler.level;

        //    if (levelScores.Count < index)
        //    {
        //        Console.WriteLine("\n\nAdding new index");
        //        levelScores.Add(new Score(ActionsHandler.level, newScore));
        //        //levelScores.Insert(index, new Score(ActionsHandler.level, newScore));
        //    }
        //    else
        //    {


        //        float oldScore = levelScores[index - 1].getScore();

        //        Console.WriteLine("\n\nOld Score: " + oldScore);
        //        Console.WriteLine("New Score: " + newScore);

        //        if (newScore > oldScore)
        //        {
        //            Console.WriteLine("Replacing index " + (index - 1));
        //            levelScores.Insert(index - 1, new Score(ActionsHandler.level, newScore));
        //        }
        //    }
            

    }
}
